#include <pjsr/StdIcon.jsh>
#include <pjsr/StdButton.jsh>
#include <pjsr/StdDialogCode.jsh>
#include <pjsr/Sizer.jsh>
#include <pjsr/FrameStyle.jsh>
#include <pjsr/TextAlign.jsh>
#include <pjsr/ColorSpace.jsh>
#include <pjsr/UndoFlag.jsh>

#define VERSION "1.0"
#define TITLE   "HMT2RecoverDetail"

///////////////////////////////////////////////////////////////////////
//
// PixInsight HDR Multiscale Transform to Recover Detail in Astrophotos
//
// https://chaoticnebula.com/pixinsight-hdr-multiscale-transform/
//
// (.20*LUM)+(.10*HDR5)+(.15*HDR6)+(.15*HDR7)+(.20*HDR8)+(.20*HDR9)
//
///////////////////////////////////////////////////////////////////////

//log output
function log(logInfo){
   Console.writeln(logInfo);
}

//search want it view
function findTargetView(viewName){

   var allWindows = ImageWindow.windows;

   var targetWindow = null;  // 用于存储找到的 ImageWindow 对象

    for (var i = 0; i < allWindows.length; ++i) {
        if (allWindows[i].mainView.id == viewName) {
            // 找到匹配的视图，返回其所在的 ImageWindow
            return allWindows[i];
        }
    }

    return null;  // 如果没有找到，返回 null
}


//create HDR layers from L layer
function CopyLayers(view,name){
   var P = new PixelMath;
   P.expression = "$T";
   P.expression1 = "";
   P.expression2 = "";
   P.expression3 = "";
   P.useSingleExpression = true;
   P.symbols = "";
   P.clearImageCacheAndExit = false;
   P.cacheGeneratedImages = false;
   P.generateOutput = true;
   P.singleThreaded = false;
   P.optimization = true;
   P.use64BitWorkingImage = false;
   P.rescale = false;
   P.rescaleLower = 0;
   P.rescaleUpper = 1;
   P.truncate = true;
   P.truncateLower = 0;
   P.truncateUpper = 1;
   P.createNewImage = true;
   P.showNewImage = true;
   P.newImageId = name;
   P.newImageWidth = 0;
   P.newImageHeight = 0;
   P.newImageAlpha = false;
   P.newImageColorSpace = PixelMath.prototype.SameAsTarget;
   P.newImageSampleFormat = PixelMath.prototype.SameAsTarget;
   return P.executeOn(view);
}


//HDRMT process
function HDRMT(view,level){
   var P = new HDRMultiscaleTransform;
   P.numberOfLayers = level;
   P.numberOfIterations = 1;
   P.invertedIterations = true;
   P.overdrive = 0.000;
   P.medianTransform = false;
   P.scalingFunctionData = [
      0.003906,0.015625,0.023438,0.015625,0.003906,
      0.015625,0.0625,0.09375,0.0625,0.015625,
      0.023438,0.09375,0.140625,0.09375,0.023438,
      0.015625,0.0625,0.09375,0.0625,0.015625,
      0.003906,0.015625,0.023438,0.015625,0.003906
   ];
   P.scalingFunctionRowFilter = [
      0.0625,0.25,
      0.375,0.25,
      0.0625
   ];
   P.scalingFunctionColFilter = [
      0.0625,0.25,
      0.375,0.25,
      0.0625
   ];
   P.scalingFunctionName = "B3 Spline (5)";
   P.deringing = false;
   P.smallScaleDeringing = 0.000;
   P.largeScaleDeringing = 0.250;
   P.outputDeringingMaps = false;
   P.midtonesBalanceMode = HDRMultiscaleTransform.prototype.Automatic;
   P.midtonesBalance = 0.500000;
   P.toLightness = false;
   P.preserveHue = false;
   P.luminanceMask = false;
   P.executeOn(view);
}

// use pixmath combine images
function pixmathDeal(view,Llayer){
	var P = new PixelMath;
	P.expression = "(.20*"+Llayer+")+(.10*HDR5)+(.15*HDR6)+(.15*HDR7)+(.20*HDR8)+(.20*HDR9)";
	P.expression1 = "";
	P.expression2 = "";
	P.expression3 = "";
	P.useSingleExpression = true;
	P.symbols = "";
	P.clearImageCacheAndExit = false;
	P.cacheGeneratedImages = false;
	P.generateOutput = true;
	P.singleThreaded = false;
	P.optimization = true;
	P.use64BitWorkingImage = false;
	P.rescale = false;
	P.rescaleLower = 0;
	P.rescaleUpper = 1;
	P.truncate = true;
	P.truncateLower = 0;
	P.truncateUpper = 1;
	P.newImageId = "LUM_HDR_DEALED";
   P.createNewImage = true;
   P.showNewImage = true;
	P.newImageWidth = 0;
	P.newImageHeight = 0;
	P.newImageAlpha = false;
	P.newImageColorSpace = PixelMath.prototype.SameAsTarget;
	P.newImageSampleFormat = PixelMath.prototype.SameAsTarget;
	return P.executeOn(view);
}


//create  L layer from RGB image
function getLChannel(targetImage){
   if(targetImage == null){
      log("No active image window!");
      throw new Error("No active image window!");
   }
   log("---active image window loaded!");

   //colorSpace must be rgb
   var colorSpace = targetImage.image.colorSpace;
   if (colorSpace != ColorSpace_RGB) {
      log("Image is not in RGB color space.");
      throw new Error("Image is not in RGB color space.");
   }
   log("---image is in RGB color space.");

   //use ChannelExtraction create L layer
   var process = new ProcessContainer;
   var ce = new ChannelExtraction;
   ce.colorSpace = ChannelExtraction.prototype.CIELab;
   ce.channels = [
      [true, ""],
      [false, ""],
      [false, ""]
   ];
   ce.sampleFormat = ChannelExtraction.prototype.SameAsSource;
   process.add(ce);
   process.executeOn(targetImage);
}

//deal process
function deal(currentL){
   //var rgbPictureName = currentView.id;// rgb picture name(id)
  // var lLayerName =  currentView.id+(new Date().getTime()); //l layer name(id)

   //1.get LUM Layer
   //getLChannel(currentView);
   //log(lLayerName);

   var L = findTargetView(currentL.id);
   /*
   var L = findTargetView(lLayerName);
   if(L){
      L.mainView.id = "LUM";
      L.show();
   }
   */

   //2.create HDR layer
   for (var i = 5; i <= 9; i++) {

      var viewStringName = "HDR"+i;

      CopyLayers(L.mainView,viewStringName);

      var result = findTargetView(viewStringName);

      if(result){
         HDRMT(result.mainView,i);
      }
   }

 
   //3.create final image layer
   var result = findTargetView(viewStringName);
   pixmathDeal(result.mainView,currentL.id);

   //4.close HDR TEMP layers and L layer
   for (var i = 5; i <= 9; i++) {

      var viewStringName = "HDR"+i;

      var result = findTargetView(viewStringName);

      if(result){
         result.forceClose();
      }
   }

   //success
   log("success");


}


//main programm
function HDRLUMDialog() {
    this.__base__ = Dialog;
    this.__base__();

    this.sizer = new VerticalSizer;
    this.sizer.margin = 6;
    this.sizer.spacing = 6;

    var emWidth = this.font.width('M');
    var labelWidth = this.font.width("Select LUM Layer:") + emWidth;

    //help label
    this.helpLabel = new Label(this);
    this.helpLabel.frameStyle = FrameStyle_Box;
    this.helpLabel.margin = 4;
    this.helpLabel.wordWrapping = true;
    this.helpLabel.useRichText = true;
    this.helpLabel.text = "A script to automatically process HDR layers 5 to 9  and finally merge them into a DEAL_LUM layer. ";
    this.sizer.add(this.helpLabel);
    this.sizer.addSpacing(4);

    //select L layer label
    this.selectFileLabel = new Label(this);
    this.selectFileLabel.text = "Select L Layer:";
    this.selectFileLabel.textAlignment = TextAlign_Right | TextAlign_VertCenter;
    this.selectFileLabel.minWidth = labelWidth;

    //layerList menu
    var currentView; //current selected layer
    this.layerList = new ViewList(this);
    this.layerList.scaledMinWidth = 100;
    this.layerList.getAll();
    this.layerList.onViewSelected = function(view) {
        currentView = view;
    };

    //add selectFileLabel and layerList to HorizontalSizer
    this.viewListHorizontalSizer = new HorizontalSizer;
    this.viewListHorizontalSizer.spacing = 6;
    this.viewListHorizontalSizer.minWidth = 10;
    this.viewListHorizontalSizer.add(this.selectFileLabel);
    this.viewListHorizontalSizer.add(this.layerList, 100);
    this.sizer.add(this.viewListHorizontalSizer);


    //ok button
    this.ok_Button = new PushButton(this);
    this.ok_Button.text = "OK";
    this.ok_Button.icon = this.scaledResource(":/icons/ok.png");
    this.ok_Button.onClick = function() {
        log("The "+currentView.id+" image has been loaded and is being prepared for processing...");
        deal(currentView)
        this.dialog.cancel();
    };

    //cancel button
    this.cancel_Button = new PushButton(this);
    this.cancel_Button.text = "Cancel";
    this.cancel_Button.icon = this.scaledResource(":/icons/cancel.png");
    this.cancel_Button.onClick = function() {
        this.dialog.cancel();
    };

    //button sizer
    this.buttons_Sizer = new HorizontalSizer;
    this.buttons_Sizer.spacing = 6;
    this.buttons_Sizer.addStretch();
    this.buttons_Sizer.add(this.ok_Button);
    this.buttons_Sizer.add(this.cancel_Button);
    this.sizer.add(this.buttons_Sizer);


    //window property
    this.windowTitle = TITLE + " Script -windystory";
    this.adjustToContents();
    this.setFixedSize();
}

HDRLUMDialog.prototype = new Dialog;

var dialog = new HDRLUMDialog();
dialog.execute();
